// $codepro.audit.disable
package org.mysofts.eclipseman.archives; // $codepro.audit.disable tooManyViolations

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.mysofts.eclipseman.util.AppLog;
import org.mysofts.eclipseman.util.MessageProvider;

/**
 * Classe qui gère des archives au format TAR.
 * 
 * @author reda
 * 
 */
final class TarArchive extends Archive { // $codepro.audit.disable
											// declareDefaultConstructors
	// [start] constructors
	/**
	 * Constructeur.
	 * 
	 * @param pArchive
	 *            Fichier archive.
	 */
	public TarArchive(final File pArchive) {
		super("tar", pArchive);
	}

	// [end]

	// [start] AbstractArchive Implémentation
	@Override
	public void archive(final File fileToArchive) throws IOException {
		throw new UnsupportedOperationException(MessageProvider.get("logs")
				.sub("archives").sub("tar").sub("archive").sub("unsupported")
				.value());
	}

	@Override
	public Collection<File> extract(final File extractTo) throws IOException {
		AppLog.debug(MessageFormat.format(
				MessageProvider.get("logs").sub("archives").sub("tar")
						.sub("extract").sub("start").value(), this
						.getArchiveFile().getAbsolutePath(), extractTo
						.getAbsolutePath()));
		Collection<File> result = new ArrayList<File>();
		try {
			InputStream is = new FileInputStream(this.getArchiveFile());
			try {
				TarArchiveInputStream tarInstrm = (TarArchiveInputStream) new ArchiveStreamFactory()
						.createArchiveInputStream(ArchiveStreamFactory.TAR, is);
				try {
					TarArchiveEntry entry = null;
					while (null != (entry = (TarArchiveEntry) tarInstrm
							.getNextEntry())) {
						final File targetFile = new File(extractTo,
								entry.getName());
						targetFile.getParentFile().mkdirs();
						if (!entry.isDirectory()) {
							final OutputStream outputFileStream = new FileOutputStream(
									targetFile);
							try {
								IOUtils.copy(tarInstrm, outputFileStream);
							} finally {
								outputFileStream.close();
							}
						} else {
							if (targetFile.getParentFile().equals(extractTo)) {
								result.add(targetFile);
							}
						}
					}
				} finally {
					tarInstrm.close();
				}
			} finally {
				is.close();
			}
			return result;
		} catch (IOException e) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("extract").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), extractTo
							.getAbsolutePath()), e);

			throw e;
		} catch (ArchiveException e) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("extract").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), extractTo
							.getAbsolutePath()), e);

			throw new IOException(e);
		} finally {
			AppLog.debug(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("extract").sub("end").value(), this
							.getArchiveFile().getAbsolutePath(), extractTo
							.getAbsolutePath(), result.toString()));
		}
	}

	@Override
	public Collection<String> listFiles() throws IOException {
		AppLog.debug(MessageFormat.format(
				MessageProvider.get("logs").sub("archives").sub("tar")
						.sub("list").sub("start").value(), this
						.getArchiveFile().getAbsolutePath()));
		List<String> list = new ArrayList<String>();
		try {
			InputStream is = new FileInputStream(this.getArchiveFile());
			try {
				TarArchiveInputStream tarInstrm = (TarArchiveInputStream) new ArchiveStreamFactory()
						.createArchiveInputStream(ArchiveStreamFactory.TAR, is);
				try {
					TarArchiveEntry entry = null;
					while (null != (entry = (TarArchiveEntry) tarInstrm
							.getNextEntry())) {
						list.add(entry.getName());
					}
				} finally {
					tarInstrm.close();
				}
			} finally {
				is.close();
			}
			return list;
		} catch (IOException ex) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("list").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), list.size()),
					ex);
			throw ex;
		} catch (ArchiveException ex) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("list").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), list.size()),
					ex);
			throw new IOException(ex);
		} finally {
			AppLog.debug(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("tar")
							.sub("list").sub("end").value(), this
							.getArchiveFile().getAbsolutePath(), list.size()));
		}
	}

	@Override
	protected Archive instanciate(final File file) {
		return new TarArchive(file);
	}

	// [end]
}
